using System.Collections.Generic;
using UnityEngine;

namespace GameToolkit
{
    /// <summary>
    /// 开启材质覆盖功能的末梢节点
    /// </summary>
    [DisallowMultipleComponent, RequireComponent(typeof(Renderer)), ExecuteAlways]
    public abstract class MaterialOverrider : MonoBehaviour
    {
        bool mIsActive;
        Renderer mRenderer;
        MaterialGroupOverrider mOverrider;
        public Renderer AttachedRenderer
        {
            get
            {
                if (mRenderer == null && this != null)
                    mRenderer = GetComponent<Renderer>();
                return mRenderer;
            }
        }

        bool mIsFeatureOn;
        public bool IsFeatureOn 
        {
            get { return mIsFeatureOn; }
            internal set
            {
                if(mIsFeatureOn != value)
                {
                    mIsFeatureOn = value;
                    if (value)
                        OnFeatureEnabled();
                    else
                        OnFeatureDisabled();
                }
            }
        }

        public MaterialGroupOverrider Overrider => mOverrider;
        public Material sharedMaterial { get { return GetMaterial(0); } set { SetMaterial(0, value); } }

        public virtual Material[] sharedMaterials
        {
            get
            {
                var r = AttachedRenderer;
                if (r != null)
                    return r.sharedMaterials;
                else
                    return null;
            }
        }

        public virtual int MaterialCount
        {
            get
            {
                var r = AttachedRenderer;
                if (r == null)
                    return 0;
                var lst = CacheUtil.GetListCahce<Material>();
                r.GetSharedMaterials(lst);
                return lst.Count;
            }
        }

        public virtual Material GetMaterial(int index)
        {
            var r = AttachedRenderer;
            if (r == null)
                return null;
            var lst = CacheUtil.GetListCahce<Material>();
            r.GetSharedMaterials(lst);
            return index < lst.Count && index >= 0 ? lst[index] : null;
        }

        public virtual void SetMaterial(int index, Material mat)
        {
            var r = AttachedRenderer;
            if (r == null || index < 0)
                return;
            if(index == 0)
            {
                r.sharedMaterial = mat;
                return;
            }
            var mats = r.sharedMaterials;
            if (index < mats.Length)
            {
                mats[index] = mat;
                r.sharedMaterials = mats;
            }
        }

        protected virtual void OnEnable()
        {
            if (mRenderer == null)
                mRenderer = GetComponent<Renderer>();
            var overrider = GetComponentInParent<MaterialGroupOverrider>();
            if (overrider != null)
            {
                mOverrider = overrider;
                overrider.Regist(this);
            }
            mIsActive = true;
        }

        protected virtual void OnDisable()
        {
            mIsActive = false;
            IsFeatureOn = false;
            if (mOverrider != null)
            {
                mOverrider.Unregist(this);
                mOverrider = null;
            }
        }

        private void OnTransformParentChanged()
        {
            if(mIsActive)
            {
                var overrider = GetComponentInParent<MaterialGroupOverrider>();
                if (overrider != mOverrider)
                {
                    if (mOverrider != null)
                        mOverrider.Unregist(this);
                    mOverrider = overrider;
                    ResetTransformParentIfNecessary();
                    if (mOverrider != null)
                        mOverrider.Regist(this);
                }
                else if (mOverrider != null)
                {
                    ResetTransformParentIfNecessary();
                    mOverrider.SetDirty(this);
                }
            }
        }

        protected virtual void ResetTransformParentIfNecessary()
        {
        }

        protected virtual void OnDestroy()
        {
            mOverrider = null;
        }
        protected abstract void OnFeatureEnabled();
        protected abstract void OnFeatureDisabled();
        internal abstract void ResetMaterialCbuffer();
        internal abstract void SetupMaterialCbuffer(ICbufferBlock cbuffer, HashSet<int> checkedId);
        internal abstract void SubmitMaterialCbuffers();
#if UNITY_EDITOR

        protected virtual void OnValidateDuringEdit(bool isActive) { }

        // 选中预览
        public virtual void OnSelectedAsPreview()
        {
            if (mRenderer == null)
                mRenderer = GetComponent<Renderer>();
        }

        private void OnValidate()
        {
            if (mOverrider == null)
                mOverrider = null;
            if (mIsActive)
            {
                var overrider = GetComponentInParent<MaterialGroupOverrider>();
                if (overrider != mOverrider)
                {
                    if (mOverrider != null)
                        mOverrider.Unregist(this);
                    mOverrider = overrider;
                    if (mOverrider != null)
                        mOverrider.Regist(this);
                }
                else if(mOverrider != null)
                {
                    mOverrider.SetDirty(this);
                }
            }
            OnValidateDuringEdit(mIsActive);
        }
#endif
    }
}
